package org.ysling.litemall.db.tenant;

import com.baomidou.mybatisplus.extension.plugins.handler.TenantLineHandler;
import com.beust.jcommander.internal.Lists;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue;
import org.apache.shiro.web.util.WebUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.util.List;
import java.util.Objects;

/**
 * 多租户处理插件
 */
public class CustomTenantLineHandler implements TenantLineHandler {

    /**租户ID*/
    private static Long tenantId = 0L;
    /**未携带请求头的请求*/
    private static final Long FAIL_TENANT_ID = -1L;
    /**默认租户*/
    private static final Long DEFAULT_TENANT_ID = 0L;
    /**租户请求头*/
    private static final String TENANT_ID_HEADER = "X-Litemall-TenantId";

    /**
     * 忽略添加租户ID的表
     */
    private static final List<String> IGNORE_TABLE_NAMES = Lists.newArrayList(
            "litemall_tenant",
            "litemall_admin",
            "litemall_permission",
            "litemall_region",
            "litemall_role",
            "litemall_category",
            "litemall_issue"
    );

    /**
     * 获取租户 ID 值表达式，只支持单个 ID 值
     * <p>
     *
     * @return 租户 ID 值表达式
     */
    @Override
    public Expression getTenantId() {
        return new LongValue(returnTenantId());
    }

    /**
     * 获取租户字段名
     * <p>
     * 默认字段名叫: tenant_id
     *
     * @return 租户字段名
     */
    @Override
    public String getTenantIdColumn() {
        return "tenant_id";
    }

    /**
     * 根据表名判断是否忽略拼接多租户条件
     * <p>
     * 默认都要进行解析并拼接多租户条件
     *
     * @param tableName 表名
     * @return 是否忽略, true:表示忽略，false:需要解析并拼接多租户条件
     */
    @Override
    public boolean ignoreTable(String tableName) {
        //未携带请求头拦截所有表
        if(tenantId.equals(FAIL_TENANT_ID)){
            return false;
        }
        //租户ID为零则忽略所有表
        if(tenantId.equals(DEFAULT_TENANT_ID)){
            return true;
        }
        return IGNORE_TABLE_NAMES.contains(tableName);
    }


    /**
     * 从请求中获取到token，从请求头中解析出tenantId
     * @return
     */
    public static Long returnTenantId() {
        //获取当前请求如果没有请求则是内部调用返回默认值
        ServletRequestAttributes sra = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        if (Objects.isNull(sra)){
            //将tenantId设置为默认值
            CustomTenantLineHandler.tenantId = DEFAULT_TENANT_ID;
            return DEFAULT_TENANT_ID;
        }
        //获取请求头如果未携带请求头则返回0
        String tenantId = WebUtils.toHttp(sra.getRequest()).getHeader(TENANT_ID_HEADER);
        if (Objects.isNull(tenantId)){
            //将tenantId设置为默认值
            CustomTenantLineHandler.tenantId = DEFAULT_TENANT_ID;
            return DEFAULT_TENANT_ID;
        }
        //获取到请求头设置请求头
        CustomTenantLineHandler.tenantId = Long.valueOf(tenantId);
        return Long.valueOf(tenantId);
    }

}
